package org.example.lotterysystem.service.activitystatus.impl;

import org.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import org.example.lotterysystem.common.exception.ServiceException;
import org.example.lotterysystem.service.ActivityService;
import org.example.lotterysystem.service.activitystatus.ActivityStatusManager;
import org.example.lotterysystem.service.activitystatus.operater.AbstractActivityOperator;
import org.example.lotterysystem.service.dto.ConvertActivityStatusDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component
public class ActivityStatusManagerImpl implements ActivityStatusManager {
    private static final Logger logger= LoggerFactory.getLogger(ActivityStatusManagerImpl.class);
    @Autowired
    //这种写法，能将AbstractActivityOperator放到hasMap中，因为加了Autowired这个注解，会被Spring管理。
    private final Map<String, AbstractActivityOperator> operatorMap=new HashMap<>();
    @Autowired
    private ActivityService activityService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        if(CollectionUtils.isEmpty(operatorMap)){
            logger.warn("operatorMap is empty");
            return;
        }
        Map<String,AbstractActivityOperator> currMap=new HashMap<>(operatorMap);

        Boolean update=false;


        //先处理：人员，奖品,这里不是多线程，代码是顺序执行的，sequence=1就是先处理活动人员，这个方法走完了，再去执行活动的操作
        processConvertStatus(convertActivityStatusDTO,currMap,1);

        //后处理活动

        update=processConvertStatus(convertActivityStatusDTO,currMap,2)|| update;
        //更新缓存，如果在处理活动的时候，发现不需要进行转换，此时返回false，就不会进入到下面的逻辑，也就是说，当返回为true时，就是活动才处理完，抽奖活动没有结束，
        // 这个值就一直为false，也就是等活动结束后再写入缓存。
        if(update){
            activityService.cacheActivity(convertActivityStatusDTO.getActivityId());

        }

    }

    private Boolean processConvertStatus(ConvertActivityStatusDTO convertActivityStatusDTO, Map<String, AbstractActivityOperator> currMap, int sequence) {
        Boolean update=false;
        //遍历currMap
        //Entry 是键值对的容器接口，常见于 Map 的实现类中（如 HashMap.Entry）。它存储一对关联数据：key 和 value。
        Iterator<Map.Entry<String ,AbstractActivityOperator>> iterator=currMap.entrySet().iterator();
        while(iterator.hasNext()){
            AbstractActivityOperator operator=iterator.next().getValue();
            //Operator是否需要转换
            if(operator.sequence()!=sequence||!operator.needConvert(convertActivityStatusDTO)){
                continue;
            }
            //走到这里说明需要转换
            if(!operator.convert(convertActivityStatusDTO)){
                logger.error("{}状态转换失败！",operator.getClass().getName());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_CONVERT_ERROR);
            }
            iterator.remove();
            update=true;
        }
        return update;



    }

    @Override
    public void rollbackHandlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        for(AbstractActivityOperator operator:operatorMap.values()){
            operator.convert(convertActivityStatusDTO);
        }
        //缓存更新
        activityService.cacheActivity(convertActivityStatusDTO.getActivityId());


    }
}
